package net.chathu.airgw.model.conn 
{
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.net.Socket;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
	import net.chathu.airgw.Config;
	import net.chathu.airgw.model.handler.IRCPacketProcessor;
	import net.chathu.airgw.packets.gw.serverpackets.*;
	import net.chathu.airgw.Soul;
	import net.chathu.airgw.util.StringUtil;

	/**
	 * ...
	 * @author ze
	 */
	public class IRCConnection 
	{
		private var readBuffer:ByteArray;
		private var socket:Socket;
		private var soul:Soul;
		private var currentNick:String = "";
		private var pingTimer:Timer;
		
		public function IRCConnection(socket:Socket, soul:Soul) 
		{
			this.socket = socket;
			this.soul = soul;
			readBuffer = new ByteArray();

			socket.addEventListener(IOErrorEvent.IO_ERROR, onIrcIOError, false, 0, true);
			socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError,false, 0, true);
			socket.addEventListener(ProgressEvent.SOCKET_DATA, onIrcData,false, 0, true);
			
			socket.addEventListener(Event.CLOSE, onIrcClose,false, 0, true);
		
			//currentNick ekkor meg ""
			//sendPacket(new EchoPacket(currentNick, " Please wait while we process your connection."));
			//020 * :Please wait while we process your connection.
			sendPacket(new EchoPacket("*", "Please wait while we process your connection."));
			
			if (Config.EXTRA_WELCOME_MESSAGE)
			{
				sendPacket(new EchoPacket("*", Config.EXTRA_WELCOME_MESSAGE));
			}
			pingTimer = new Timer(60000, 0);
			pingTimer.addEventListener(TimerEvent.TIMER, onPingNeeded);
			pingTimer.start();
		}
	

		
		private function onIrcIOError(e:IOErrorEvent):void
		{
			trace("onIrcIOError");
			
		}
		
		private function onIrcData(e:ProgressEvent):void
		{

			var incoming:ByteArray = new ByteArray();
			socket.readBytes(incoming, 0, socket.bytesAvailable);
			
			
			//trace("incoming position:" + incoming.position);
			//trace("incoming bytesAvailable:" + incoming.bytesAvailable);
			//trace("incoming length:" + incoming.length);
			
			
			readBuffer.writeBytes(incoming, 0, incoming.length); //hozzairas a readBufferhez
			
		
			//try to read irc commands:
			var packetStartPos:int = 0;
			//var packetEnd:Boolean;

			for (readBuffer.position = packetStartPos; readBuffer.position + 1 <= readBuffer.length;)
			{
				var byte:int = readBuffer.readByte();
				var char:String = String.fromCharCode(byte);
				if (char == "\n")
				{
					//egy parancs vegehez ertunk!

					//a kov csomag kezdetenek pozicioja
					var tmp:int = readBuffer.position;
					
					readBuffer.position = packetStartPos;
					var inputStr:String = readBuffer.readMultiByte(tmp - 1 - packetStartPos, Config.IRC_ENCODING);

					inputStr = StringUtil.trim(inputStr);
					var packetData:Array = inputStr.split(" ");
					
					trace("input: " + inputStr);
					//handle packet...
					IRCPacketProcessor.handlePacket(packetData, soul.sessionData);

					readBuffer.position = tmp;
					packetStartPos = tmp;
				}
			}

			if (packetStartPos > 0)
			{
				var newReadBuffer:ByteArray = new ByteArray();
				newReadBuffer.writeBytes (readBuffer, packetStartPos, 0);//0 means all available bytes
				readBuffer = newReadBuffer;
			}
		}
		
		private function onSecurityError(e:SecurityErrorEvent):void
		{
			trace("onSecurityError");
			
		}
		
		private function onIrcClose(e:Event):void
		{
			//............nooo!
			//var socket:Socket = Socket(e.target);
			//destroy soul
			trace("IRC Client terminated connection");
			if (pingTimer)
			{
				pingTimer.stop();
				pingTimer.removeEventListener(TimerEvent.TIMER, onPingNeeded);
				pingTimer = null;
			}
			soul.destroy();
			
		}
		
		/*public function sendMessage(message:String):void
		{	
			if (socket.connected)
			{
				try {
				
					socket.writeUTFBytes(message);
					socket.flush();
				} catch (err:Error) {
					trace("Unable to write to socket: " + err.message);
				}
			}
		}*/
		
		public function sendPacket(packet:ISendableIRCPacket):void
		{
			//sendMessage(packet.getMessage());
			if (socket.connected)
			{
				try {
					socket.writeMultiByte(packet.getMessage(), Config.IRC_ENCODING);
					//socket.writeUTFBytes(packet.getMessage());
					socket.flush();
				} catch (err:Error) {
					trace("Unable to write to socket: " + err.message);
				}
			}
		}
		
		public function get connected():Boolean {
			return socket.connected;
		}
		
		public function close():void {
			socket.close();
		}
	
		private function onPingNeeded(event:TimerEvent):void {
			if (connected)
			{
				sendPacket(new PingPacket(Config.IRC_HOST));
			}
		}

		
	}

}